package com.yuandengta.yomall.member.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.yuandengta.common.exception.BizCode;
import com.yuandengta.common.utils.HttpUtils;
import com.yuandengta.common.utils.JsonUtils;
import com.yuandengta.yomall.member.dao.MemberLevelDao;
import com.yuandengta.yomall.member.entity.MemberLevelEntity;
import com.yuandengta.yomall.member.exception.MemberException;
import com.yuandengta.yomall.member.vo.MemberLoginVO;
import com.yuandengta.yomall.member.vo.MemberRegisterVO;
import com.yuandengta.yomall.member.vo.WeiboUser;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuandengta.common.utils.PageUtils;
import com.yuandengta.common.utils.Query;

import com.yuandengta.yomall.member.dao.MemberDao;
import com.yuandengta.yomall.member.entity.MemberEntity;
import com.yuandengta.yomall.member.service.MemberService;


@Service("memberService")
public class MemberServiceImpl extends ServiceImpl<MemberDao, MemberEntity> implements MemberService {

    @Autowired
    private MemberLevelDao memberLevelDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<MemberEntity> page = this.page(
                new Query<MemberEntity>().getPage(params),
                new QueryWrapper<MemberEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 检查手机号唯一
     * @param mobile
     * @return
     */
    @Override
    public void checkMobileUnique(String mobile) throws MemberException {
        Integer count = baseMapper.selectCount(new QueryWrapper<MemberEntity>().eq("mobile", mobile));
        if (count > 0) {
            throw new MemberException(BizCode.MOBILE_EXIST_EXCEPTION.getMessage(), BizCode.MOBILE_EXIST_EXCEPTION.getCode());
        }
    }

    /**
     * 检查用户名唯一
     * @param username
     * @return
     */
    @Override
    public void checkUsernameUnique(String username) throws MemberException {
        Integer count = baseMapper.selectCount(new QueryWrapper<MemberEntity>().eq("username", username));
        if (count > 0) {
            throw new MemberException(BizCode.USER_EXIST_EXCEPTION.getMessage(), BizCode.USER_EXIST_EXCEPTION.getCode());
        }
    }

    /**
     * 会员注册
     * @param registerVO
     */
    @Override
    public void register(MemberRegisterVO registerVO) {
        // 检查用户名和手机号唯一
        checkUsernameUnique(registerVO.getUsername());
        checkMobileUnique(registerVO.getMobile());
        // 设置用户名和手机号
        MemberEntity memberEntity = new MemberEntity();
        memberEntity.setUsername(registerVO.getUsername());
        memberEntity.setMobile(registerVO.getMobile());
        // 设置昵称，默认是注册用户名
        memberEntity.setNickname(registerVO.getUsername());

        // 设置会员默认等级
        MemberLevelEntity memberLevelEntity = memberLevelDao.getDefaultLevel();
        memberEntity.setLevelId(memberLevelEntity.getId());

        // 设置密码, 进行盐值加密处理
        // BCryptPasswordEncoder.encode() 加密：先生成盐值，根据盐值以及明文密码生成密文
        // BCryptPasswordEncoder.matches(登录密码，数据库存储密文) 密码匹配
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encodePassword = passwordEncoder.encode(registerVO.getPassword());
        memberEntity.setPassword(encodePassword);

        // 保存
        save(memberEntity);
    }

    /**
     * 会员登录
     * @param vo
     * @return
     */
    @Override
    public MemberEntity login(MemberLoginVO vo) {
        String account = vo.getAccount();
        String password = vo.getPassword();

        // 数据库查询密文密码
        MemberEntity entity = baseMapper.selectOne(new QueryWrapper<MemberEntity>()
                .eq("username", account).or().eq("mobile", account));
        if (entity != null) {
            // 密文
            String passwordDb = entity.getPassword();
            // 密码匹配
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            boolean matches = passwordEncoder.matches(password, passwordDb);
            if (matches) {
                return entity;
            } else {
                return null;
            }
        }
        return null;
    }

    /**
     * 微博登录
     * @param weiboUser
     * @return
     */
    @Override
    public MemberEntity login(WeiboUser weiboUser) {
        // 登录和注册合并逻辑
        // 判断当前微博用户是否已经登录过
        MemberEntity memberEntity = baseMapper.selectOne(new QueryWrapper<MemberEntity>()
                .eq("weibo_uid", weiboUser.getUid()));
        if (memberEntity != null) {
            // 用户已经注册，更新access_token和expires_in
           MemberEntity updateEntity = new MemberEntity();
           updateEntity.setId(memberEntity.getId());
           updateEntity.setAccessToken(weiboUser.getAccess_token());
           updateEntity.setExpiresIn(weiboUser.getExpires_in());
           baseMapper.updateById(updateEntity);

           memberEntity.setAccessToken(weiboUser.getAccess_token());
           memberEntity.setExpiresIn(weiboUser.getExpires_in());
           return memberEntity;
        } else {
            // 没有查到微博用户，则需要注册
            MemberEntity regEntity = new MemberEntity();
            // 查询当前微博用户的社交账号信息（昵称，性别等）
            Map<String, String> querys = new HashMap<>(2);
            querys.put("access_token", weiboUser.getAccess_token());
            querys.put("uid", weiboUser.getUid());
            try {
                HttpResponse response = HttpUtils.doGet("https://api.weibo.com", "/2/users/show.json",
                        "get", new HashMap<String, String>(0), querys);
                if (response.getStatusLine().getStatusCode() == 200) {
                    String json = EntityUtils.toString(response.getEntity());

                    Map<String, String> map = JsonUtils.jsonToObject(json, new TypeReference<Map>() {});
                    // 昵称
                    String name = map.get("name");
                    // 性别
                    String gender = map.get("gender");
                    regEntity.setNickname(name);
                    regEntity.setGender("m".equals(gender)?1:0);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            regEntity.setWeiboUid(weiboUser.getUid());
            regEntity.setAccessToken(weiboUser.getAccess_token());
            regEntity.setExpiresIn(weiboUser.getExpires_in());
            baseMapper.insert(regEntity);

            return regEntity;
        }
    }

}